# -*- coding: utf-8 -*-
"""
-------------------------------------------------
File Name： row_sort_util
Description :
Author : 'li'
date： 2020/11/3
-------------------------------------------------
Change Activity:
2020/11/3:
-------------------------------------------------
"""

import copy

from ml.cv.util.distance import get_distance


class RowSortUtil:
    def __init__(self, text_area_descriptions, max_interval=100):
        """

        :param text_area_descriptions:
        """
        self.max_interval = max_interval
        self.original_text_area_descriptions = text_area_descriptions
        self.rows = []
        self.left_items = copy.deepcopy(self.original_text_area_descriptions)

    def sort_row(self):
        if len(self.original_text_area_descriptions) == 0:
            return []
        all_rows = self._create_rows()
        self._sort_rows(all_rows)
        return all_rows

    @staticmethod
    def _sort_rows(all_rows):
        if len(all_rows) < 2:
            return all_rows
        total_size = len(all_rows)
        for i in range(total_size - 1):
            for j in range(i + 1, total_size):
                if all_rows[j][0].center_point[1] < all_rows[i][0].center_point[1]:
                    tmp_row = all_rows[j]
                    all_rows[j] = all_rows[i]
                    all_rows[i] = tmp_row

    def _create_rows(self):
        """

        :return:
        """
        all_rows = []
        while True:
            if len(self.left_items) == 0:
                return all_rows
            row = self._build_one_row()
            all_rows.append(row)

    def _build_one_row(self):
        row = [self.left_items.pop(0)]
        while True:
            is_insert = False
            left_neighbor_index, distance = self._get_left_neighbor(row)
            if distance < self.max_interval:
                tmp_item = self.left_items.pop(left_neighbor_index)
                row.insert(0, tmp_item)
                is_insert = True
            close_item_index, close_distance = self._get_right_neighbor(row)
            if close_distance < self.max_interval:
                tmp_item = self.left_items.pop(close_item_index)
                row.append(tmp_item)
                is_insert = True
            if not is_insert:
                return row

    def _get_left_neighbor(self, row):
        anchor_item = row[0]
        close_distance = 1000
        close_item_index = None
        for index, item in enumerate(self.left_items):
            start_1 = item.box_coordinate[1][1]
            start_2 = item.box_coordinate[2][1]
            end_1 = anchor_item.box_coordinate[0][1]
            end_2 = anchor_item.box_coordinate[3][1]
            if self.is_intersect(end_1, end_2, start_1, start_2):
                anchor_meddle = (anchor_item.box_coordinate[0] + anchor_item.box_coordinate[3]) / 2
                left_meddle = (item.box_coordinate[1] + item.box_coordinate[2]) / 2
                if left_meddle[0] - anchor_meddle[0] > 4:
                    continue
                distance = get_distance(left_meddle, anchor_meddle)
                if distance < close_distance:
                    close_distance = distance
                    close_item_index = index
        return close_item_index, close_distance

    def _get_right_neighbor(self, row):
        """
        get right neighbor
        :param row:
        :return:
        """
        anchor_item = row[-1]
        close_distance = 1000
        close_item_index = None
        for index, item in enumerate(self.left_items):
            start_1 = anchor_item.box_coordinate[1][1]
            start_2 = anchor_item.box_coordinate[2][1]
            end_1 = item.box_coordinate[0][1]
            end_2 = item.box_coordinate[3][1]
            if self.is_intersect(end_1, end_2, start_1, start_2):
                anchor_meddle = (anchor_item.box_coordinate[1] + anchor_item.box_coordinate[2]) / 2
                right_meddle = (item.box_coordinate[0] + item.box_coordinate[3]) / 2
                if anchor_meddle[0] > right_meddle[0] + 4:
                    continue
                distance = get_distance(anchor_meddle, right_meddle)
                if distance < close_distance:
                    close_distance = distance
                    close_item_index = index
        return close_item_index, close_distance

    @staticmethod
    def is_intersect(end_1, end_2, start_1, start_2):
        """
        check is intersect
        :param end_1:   point
        :param end_2: point
        :param start_1: point
        :param start_2: point
        :return:
        """
        ra_1 = []
        a_inter_b = False
        b_inter_a = False
        for i in range(int(end_1), int(end_2)):
            if start_1 < i < start_2:
                ra_1.append(i)
        if len(ra_1) / (abs(end_2 - end_1) + 0.01) > 0.3:
            a_inter_b = True
        ra_1 = []
        for i in range(int(start_1), int(start_2)):
            if end_1 < i < end_2:
                ra_1.append(i)
        if len(ra_1) / (abs(start_2 - start_1) + 0.01) > 0.3:
            b_inter_a = True
        if a_inter_b and b_inter_a:
            return True
        return False


if __name__ == '__main__':
    a = [1, 2, 3, 4, 3, 4, 5, 6, 76, 7, 8, 9]
    a.insert(0, 123)
    print(a)
